package com.start.quartz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.start.common.exceptions.StartBusException;
import com.start.quartz.entity.StartQuartzEntity;
import com.start.quartz.mappers.StartQuartzMapper;
import com.start.quartz.model.StartQuartzEntityModel;
import com.start.quartz.service.StartQuartzService;
import lombok.SneakyThrows;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class StartQuartzServiceImpl extends ServiceImpl<StartQuartzMapper, StartQuartzEntity> implements StartQuartzService {


    @Autowired
    private Scheduler scheduler;

    @SneakyThrows
    @Override
    @Transactional
    public void activeTask(String id) {
        StartQuartzEntity quartzEntity = getById(id);
        activeTask(quartzEntity, true);
    }

    private void activeTask(StartQuartzEntity quartzEntity, boolean throwsException) {
        JobKey jobKey = new JobKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        try {
            if (scheduler.checkExists(jobKey)) {
                if (throwsException) throw new StartBusException("任务已经激活");
                return;
            }
            Class<?> clazz = Class.forName(quartzEntity.getClassPath());
            if (!Job.class.isAssignableFrom(clazz))
                throw new StartBusException(quartzEntity.getClassPath() + "该任务类不是一个有效的任务");
            Class<? extends Job> jobClazz = (Class<? extends Job>) clazz;
            JobDetail detail = JobBuilder.newJob(jobClazz).withDescription(quartzEntity.getDescrption()).withIdentity(jobKey).build();
            if (quartzEntity.getContextMapData() != null && quartzEntity.getContextMapData().size() > 0) {
                detail.getJobDataMap().putAll(quartzEntity.getContextMapData());
            }
            Trigger trigger = TriggerBuilder
                    .newTrigger()
                    .forJob(detail)
                    .withIdentity(quartzEntity.getId(), quartzEntity.getGroupKey())
                    .withSchedule(CronScheduleBuilder.cronSchedule(quartzEntity.getCron()))
                    .startNow()
                    .build();
            scheduler.scheduleJob(detail, trigger);
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
            quartzEntity.setIsEnable(1);
            updateById(quartzEntity);
        } catch (ClassNotFoundException | SchedulerException e) {
            throw new StartBusException("任务类不存在");
        }

    }


    @Override
    public void disableTask(String id) throws SchedulerException {
        StartQuartzEntity quartzEntity = getById(id);
        if (quartzEntity == null) return;
        disableTask(quartzEntity, false);
    }

    private void disableTask(StartQuartzEntity quartzEntity, boolean throwsException) throws SchedulerException {
        JobKey jobKey = new JobKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        if (!scheduler.checkExists(jobKey)) {
            if (throwsException) throw new StartBusException("任务已经停止");

        } else {
            TriggerKey triggerKey = TriggerKey.triggerKey(quartzEntity.getId(), quartzEntity.getGroupKey());
            scheduler.pauseTrigger(triggerKey);// 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            scheduler.deleteJob(JobKey.jobKey(quartzEntity.getId(), quartzEntity.getGroupKey()));// 删除任务
        }
        quartzEntity.setIsEnable(0);
        updateById(quartzEntity);
    }

    @Override
    public void deleteTask(String id) {
        try {
            disableTask(id);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        removeById(id);
    }

    @Override
    public void pauseTask(String id) throws SchedulerException {
        StartQuartzEntity quartzEntity = getById(id);
        JobKey jobKey = new JobKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        if (!scheduler.checkExists(jobKey)) {
            throw new StartBusException("任务已经停止");
        }
        TriggerKey triggerKey = TriggerKey.triggerKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        scheduler.pauseTrigger(triggerKey);// 停止触发器
    }

    @Override
    public void pauseAll() throws SchedulerException {
        scheduler.pauseAll();
    }

    @Override
    public void startTask(String id) throws SchedulerException {
        StartQuartzEntity quartzEntity = getById(id);
        JobKey jobKey = new JobKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        if (!scheduler.checkExists(jobKey)) {
            throw new StartBusException("任务未激活请激活任务后在操作");
        }
        scheduler.triggerJob(jobKey);
    }

    @Override
    public void recovery(String id) throws SchedulerException {
        StartQuartzEntity quartzEntity = getById(id);
        JobKey jobKey = new JobKey(quartzEntity.getId(), quartzEntity.getGroupKey());
        if (!scheduler.checkExists(jobKey)) {
            throw new StartBusException("任务已经停止");
        }
        scheduler.resumeJob(jobKey);
    }

    @Override
    public void recoveryAll() throws SchedulerException {
        scheduler.resumeAll();
    }

    @Override
    @Transactional
    public void updateTask(StartQuartzEntity sysQuartz) throws SchedulerException {
        StartQuartzEntity oldSysQuartz = getById(sysQuartz.getId());
        JobKey jobKey = new JobKey(oldSysQuartz.getId(), oldSysQuartz.getGroupKey());
        if (!scheduler.checkExists(jobKey)) {
            updateById(sysQuartz);
            return;
        }
        disableTask(sysQuartz, false);
        activeTask(sysQuartz, true);
        updateById(sysQuartz);
    }

    @Override
    public Page<StartQuartzEntityModel> pageQuartzEntityModel(Page<StartQuartzEntityModel> page, QueryWrapper<StartQuartzEntityModel> queryWrapper) {
        return getBaseMapper().pageQuartzEntityModel(page, queryWrapper);
    }

    @Override
    public StartQuartzEntityModel getQuartById(String id) {
        return baseMapper.getQuartById(id);
    }
}